﻿namespace CollisionDetection.ViewModels
{
    using System;
    using System.ComponentModel;
    using System.Configuration;
    using System.Diagnostics;
    using System.IO;
    using System.Text;
    using System.Windows.Forms;
    using Models;

    public class ImportadorViewModel : INotifyPropertyChanged
    {
        #region Fields

        private string _csvPath;
        private string _xmlPath;
        private bool _isImporting;

        private EnumTipoImportacao _tipoImportacao;

        private StringBuilder _output;

        #endregion

        #region Properties

        public string CsvPath
        {
            get { return _csvPath; }
            set
            {
                _csvPath = value;
                InvokePropertyChanged("CsvPath");
            }
        }
        public string XmlPath
        {
            get { return _xmlPath; }
            set
            {
                _xmlPath = value;
                InvokePropertyChanged("XmlPath");
            }
        }
        public bool IsImporting
        {
            get { return _isImporting; }
            set
            {
                _isImporting = value;
                InvokePropertyChanged("IsImporting");
                InvokePropertyChanged("IsNotImporting");
            }
        }
        public bool IsNotImporting
        {
            get { return !_isImporting; }
        }

        public EnumTipoImportacao TipoImportacao
        {
            get { return _tipoImportacao; }
            set
            {
                _tipoImportacao = value;
                Output = string.Format("Importação para {0}{1}",
                                       _tipoImportacao.ToString().Substring(2, _tipoImportacao.ToString().Length - 2), Environment.NewLine);
                InvokePropertyChanged("TipoImportacao");
            }
        }

        public string Output
        {
            get { return _output.ToString(); }
            set
            {
                _output = new StringBuilder(value);
                InvokePropertyChanged("Output");
            }
        }

        #endregion

        #region Constructors

        public ImportadorViewModel()
        {
            var d = new AppSettings();
            CsvPath = d.CsvPath;
            XmlPath = d.XmlPath;
            TipoImportacao = d.TipoImportacao;
        }

        ~ImportadorViewModel()
        {
            var d = new AppSettings();
            d.CsvPath = CsvPath;
            d.XmlPath = XmlPath;
            d.TipoImportacao = TipoImportacao;
            d.Save();
        }

        #endregion

        #region Events

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region Members

        public void Importar()
        {
            if (!Directory.Exists(_csvPath))
            {
                OutputAppendLine("Directório não existe!");
                return;
            }

            switch (TipoImportacao)
            {
                case EnumTipoImportacao.tiXml:
                    ImportarToXml();
                    break;
                case EnumTipoImportacao.tiDatabase:
                    ImportarToDatabase();
                    break;

            }
        }

        public void CsvPathDialog()
        {
            var dialog = new FolderBrowserDialog();
            dialog.SelectedPath = CsvPath;
            dialog.Description = "Indique o directório onde se encontram os ficheiros de dados em formato CSV";
            if (dialog.ShowDialog()==DialogResult.OK)
            {
                CsvPath = Path.GetFullPath(dialog.SelectedPath);
            }
        }
        
        public void XmlPathDialog()
        {
            var dialog = new FolderBrowserDialog();
            dialog.SelectedPath = XmlPath;
            dialog.Description = "Indique o directório onde pretende criar os dados em formato XML";
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                XmlPath = Path.GetFullPath(dialog.SelectedPath);
            }
        }

        protected void InvokePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler changed = PropertyChanged;
            if (changed != null) changed(this, new PropertyChangedEventArgs(propertyName));
        }

        private void ImportarToDatabase()
        {
            IsImporting = true;
            _output.Remove(0, _output.Length);
            OutputAppendLine("Iniciar importação para Base de dados");

            //Inicializa o processo de uma shell para executar os comandos para o cliente
            var executable = Path.GetFullPath(ConfigurationManager.AppSettings["ImportarCsvToDatabaseExecutable"]);
            ExecuteImportProcess(executable, string.Format("CsvPath={0} XmlPath={1}", _csvPath, _xmlPath));
        }

        private void ImportarToXml()
        {
            IsImporting = true;
            _output.Remove(0, _output.Length);
            OutputAppendLine("Iniciar importação para XML");

            //Inicializa o processo de uma shell para executar os comandos para o cliente
            var executable = Path.GetFullPath(ConfigurationManager.AppSettings["ImportarCsvToXmlExecutable"]);
            ExecuteImportProcess(executable, string.Format("CsvPath={0} XmlPath={1}", _csvPath, _xmlPath));
        }

        private void ExecuteImportProcess(string executable, string arguments)
        {
            var workingDir = Path.GetDirectoryName(executable);

            var si = new ProcessStartInfo(executable)
                         {
                             RedirectStandardInput = true,
                             RedirectStandardOutput = true,
                             RedirectStandardError = true,
                             UseShellExecute = false,
                             WindowStyle = ProcessWindowStyle.Hidden,
                             CreateNoWindow = true,
                             WorkingDirectory = workingDir,
                             Arguments = arguments
                         };
            var process = Process.Start(si);
            if (process == null)
                throw new Exception("Não foi possivel executar o comando.\nVerifique que o comando externo para importação está correctamente configurado.");

            process.OutputDataReceived += ProcessOutputDataReceived;
            process.ErrorDataReceived += ProcessOutputDataReceived;
            process.BeginOutputReadLine();
            var work = new BackgroundWorker();
            work.DoWork += (s,e) => {
                                       process.WaitForExit();
                                       IsImporting = false;
            };
            work.RunWorkerAsync();
        }

        private void ProcessOutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            OutputAppendLine(e.Data);
        }

        private void OutputAppendLine(string line)
        {
            _output.AppendLine(line);
            InvokePropertyChanged("Output");            
        }

        #endregion
    }
}


